﻿using System; 
using System.Collections.Generic; 
using UnityEngine;
using XFABManager;

namespace XFGameFramework
{



    public class ModuleManager
    {
        #region 字段
        internal static Dictionary<string, Module> modules = new Dictionary<string, Module>();

        internal static Dictionary<string, Module> baseModules = new Dictionary<string, Module>();

        internal static Dictionary<string, CustomYieldInstruction> starting_up_module = new Dictionary<string, CustomYieldInstruction>(); // 启动中的模块

        private static Module current_module;

        #endregion

        #region 方法

        [RuntimeInitializeOnLoadMethod]
        static void Init()
        {
            modules.Clear();
            baseModules.Clear();
            starting_up_module.Clear();
            current_module = null;
        }


        /// <summary>
        /// 添加模块
        /// </summary>
        /// <param name="module">模块对象</param>
        internal static void AddModule(Module module)
        {

            if (!modules.ContainsKey(module.ModuleName))
                modules.Add(module.ModuleName, module);

            if (module.BaseModule && !baseModules.ContainsKey(module.ModuleName))
            {
                baseModules.Add(module.ModuleName, module);
            }

            current_module = module;
        }

        /// <summary>
        /// 查询模块
        /// </summary>
        /// <param name="moduleTypeFullName">模块类型名称(含命名空间)</param>
        /// <returns></returns>
        public static Module GetModule(string moduleTypeFullName)
        {

            Module m;
            if (modules.TryGetValue(moduleTypeFullName, out m))
            {
                return m;
            }
            return null;

        }

        /// <summary>
        /// 查询模块(泛型方式)
        /// </summary>
        /// <typeparam name="T">类型</typeparam>
        /// <returns></returns>
        public static T GetModule<T>() where T : Module
        {
            return GetModule(typeof(T).FullName) as T;
        }

        /// <summary>
        /// 关闭模块
        /// </summary>
        /// <param name="moduleTypeFullName">模块类型名称(含命名空间)</param>
        public static void CloseModule(string moduleTypeFullName)
        {
            Module module = GetModule(moduleTypeFullName);

            if (module != null)
                module.OnExit();
            else
                Debug.LogWarningFormat("未查询到模块:{0}", moduleTypeFullName);

            // 清空表引用
            if (modules.ContainsKey(moduleTypeFullName))
                modules.Remove(moduleTypeFullName);
            if (baseModules.ContainsKey(moduleTypeFullName))
                baseModules.Remove(moduleTypeFullName);

            // 清空当前模块
            if (module == current_module)
                current_module = null;
        }

        /// <summary>
        /// 关闭模块(泛型方式)
        /// </summary>
        /// <typeparam name="T">模块类型</typeparam>
        public static void CloseModule<T>() where T : Module
        {
            CloseModule(typeof(T).FullName);
        }

        /// <summary>
        /// 启动模块
        /// </summary>
        /// <param name="module">模块对象</param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public static StartUpModuleRequest StartUpModule(Module module)
        {
            if (module == null) throw new Exception("module is null!");


            string key = string.Format("StartUpModule:{0}", module.ModuleName);
            return AssetBundleManager.ExecuteOnlyOnceAtATime<StartUpModuleRequest>(key, () =>
            {
                StartUpModuleRequest request = new StartUpModuleRequest();
                CoroutineStarter.Start(request.StartUp(module));
                return request;
            });
        }

        /// <summary>
        /// 启动模块(根据类型启动)
        /// </summary>
        /// <param name="moduleType">模块类型</param>
        /// <returns></returns>
        /// <exception cref="Exception"></exception>
        public static StartUpModuleRequest StartUpModule(Type moduleType)
        {
            if (moduleType == null)
                throw new Exception("moduleType is null!");

            Module module = Activator.CreateInstance(moduleType) as Module;
            return StartUpModule(module);
        }

        /// <summary>
        /// 启动模块(泛型方式)
        /// </summary>
        /// <typeparam name="T">模块类型</typeparam>
        /// <returns></returns>
        public static StartUpModuleRequest StartUpModule<T>() where T : Module
        {
            Module module = Activator.CreateInstance<T>();
            return StartUpModule(module);
        }

        /// <summary>
        /// 启动模块(根据类名)
        /// </summary>
        /// <param name="moduleTypeFullName">模块类型名称(含命名空间)</param>
        /// <returns></returns>
        public static StartUpModuleRequest StartUpModule(string moduleTypeFullName)
        {
            Type type = AssemblyTools.GetType(moduleTypeFullName);
            return StartUpModule(type);
        }



        /// <summary>
        /// 获取当前使用的模块
        /// </summary>
        /// <returns></returns>
        internal static Module GetCurrentModule()
        {
            if (modules.Count == 1)
            {
                foreach (var item in modules.Values)
                    return item;
            }

            if (current_module != null)
                return current_module;

            // 
            if (baseModules.Count == modules.Count)
            {
                // 返回一个基础模块 
                foreach (var item in baseModules.Values)
                    return item;
            }
            else
            {
                // 找到一个不是基础模块的模块
                foreach (var item in modules.Values)
                {
                    if (item.BaseModule) continue;
                    return item;
                }
            }

            return null;
        }

        internal static Module GetControllerModule(Module ignore)
        {
            // 优先找到一个基础模块
            foreach (var item in baseModules.Values)
            {
                if (item == ignore) continue;
                return item;
            }
            // 如果没有 找一个默认的
            foreach (var item in modules.Values)
            {
                if (item == ignore) continue;
                return item;
            }
            return null;
        }

        #endregion
    }

}
